# Copyright (C) 2003-2004, 2006, 2008, 2009 The Written Word, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# $Id: textgroup.py 694 2010-02-19 14:55:45Z china $

import cgi
import re
import sys

# build text for <item> or <para>
def build_item_text (items, program = None):
  text = ''

  for item_entry in items:
    if item_entry.type == 'command':
      text += '<command>' + cgi.escape (item_entry.text) + '</command>'
    elif item_entry.type == 'link':
      text += '<ulink url="' + cgi.escape (item_entry.url) + \
              '">' + cgi.escape (item_entry.value) + '</ulink>'
    elif item_entry.type == 'text':
      text += cgi.escape (item_entry.text)

  # substitute ${SB_INSTALL_PREFIX} and ${SB_INSTALL_NAME}
  text = replace_sb_vars (text, program)

  return text

# replace ${SB...} variables unless preceded by '\'
def replace_sb_vars (text, program):
  if program:
    text = re.sub ('\${SB_INSTALL_BASE}',
                   program.install_base.path, text)
    text = re.sub ('\${SB_INSTALL_NAME}',
                   program.get_install_path (), text)
    text = re.sub ('(?<!\\\)\${SB_INSTALL_PREFIX}',
                   program.get_install_prefix (), text)
    text = re.sub ('\\\\\${SB_INSTALL_PREFIX}',
                   '${SB_INSTALL_PREFIX}', text)
    text = re.sub ('(?<!\\\)\${SB_PROG_NAME}',
                   program.prog_name, text)
    text = re.sub ('\\\\\${SB_PROG_NAME}',
                   program.prog_name, text)
    text = re.sub ('(?<!\\\)\${SB_PROG_VER}',
                   program.prog_ver, text)
    text = re.sub ('\\\\\${SB_PROG_VER}',
                   program.prog_ver, text)

  return text

# print <changelog> entry
def print_changelog (program, query_indent, substitute_vars = True):
  indent = ' ' * query_indent

  changelog = program.sbdb.changelog[:]
  if changelog:
    print indent + '\
<changelog>'

    while changelog:
      change = changelog.pop (0)

      print indent + '\
  <change date="' + change.date + '" revision="' + change.revision + '"'
      print indent + '\
  author="' + change.author + '" email="' + change.email + '">'

      if substitute_vars:
        print_change_entries (change.items[:], query_indent + 4, program)
      else:
        print_change_entries (change.items[:], query_indent + 4)

      print indent + '\
  </change>'

      if changelog:
        print

    print indent + '\
</changelog>'

# print <change> entries
def print_change_entries (items, indent, program = None):
  indent_space = ' ' * indent

  while items:
    item = items.pop (0)

    if item.type == 'item':
      print_item_entry (item.items[:], indent, program)
    elif item.type == 'item group':
      print indent_space + '\
<items name="' + item.group + '">'

      print_change_entries (item.items, indent + 2, program)

      print indent_space + '\
</items>'

      if items:
        print
    elif item.type == 'orderedlist':
      sys.stdout.write (indent_space + '<orderedlist')
      if item.list_type != 'decimal':
        sys.stdout.write (' type="' + item.list_type + '"')
      if item.start_num != '1':
        sys.stdout.write (' start-num="' + item.start_num + '"')
      sys.stdout.write ('>\n')

      for list_item in item.items:
        if list_item.type == 'item':
          print_item_entry (list_item.items[:], indent + 2, program)

      print indent_space + '</orderedlist>'
    elif item.type == 'para':
      print indent_space + '\
<para>' + build_item_text (item, program) + '</para>'
    elif item.type == 'screen':
      text = cgi.escape (item.text)
      print indent_space + '\
<screen>\n' + replace_sb_vars (text, program) + '\n' + \
            indent_space + '</screen>'
    elif item.type == 'unorderedlist':
      sys.stdout.write (indent_space + '<unorderedlist>\n')

      for list_item in item.items:
        if list_item.type == 'item':
          print_item_entry (list_item.items[:], indent + 2, program)

      print indent_space + '</unorderedlist>'

# print <licenses> entry
def print_licenses (program, query_indent, substitute_vars = True):
  indent = ' ' * query_indent

  licenses = program.sbdb.licenses[:]
  if licenses:
    print indent + '\
<licenses>'

    while licenses:
      license = licenses.pop (0)

      if substitute_vars:
        print_license_entry (license, query_indent + 2, program)
      else:
        print_license_entry (license, query_indent + 2)

      if licenses:
        print

    print indent + '\
</licenses>'


# print <license> entry
def print_license_entry (license, indent, program = None):
  indent_space = ' ' * indent

  items = license.items[:]
  sys.stdout.write (indent_space + '<license')
  if license.module:
    sys.stdout.write (' module="' + license.module + '"')
  if license.path:
    sys.stdout.write (' path="' + license.path + '"')
  if not items:
    print '/>'
  else:
    print '>'
    print_textgroup_entry (items, indent, program)

    print indent_space + '\
</license>'

# print <notes> entry
def print_notes (program, query_indent, substitute_vars = True):
  indent = ' ' * query_indent

  notes = program.sbdb.notes[:]
  while notes:
    notes_entry = notes.pop (0)

    sys.stdout.write (indent + '\
<notes')
    if notes_entry.name:
      sys.stdout.write (' name="' + notes_entry.name + '"')
    print '>'

    notes_entry_items = notes_entry[:]
    while notes_entry_items:
      notes_entry_item = notes_entry_items.pop (0)

      if notes_entry_item.type == 'change':
        print indent + '\
  <change from="' + notes_entry_item.from_version + '" to="' + \
              notes_entry_item.to_version + '">'

        if substitute_vars:
          print_change_entries (notes_entry_item.items[:], query_indent + 4,
                                program)
        else:
          print_change_entries (notes_entry_item.items[:], query_indent + 4)

        print indent + '\
  </change>'
      else:
        if substitute_vars:
          print_note_entry (notes_entry_item, query_indent + 2, program)
        else:
          print_note_entry (notes_entry_item, query_indent + 2)

      if notes_entry_items:
        print
    print indent + '\
</notes>'

    # separate <notes> entries with newline
    if notes:
      print

# print <note> and <platform> entry
def print_note_entry (note, indent, program = None):
  indent_space = ' ' * indent

  if note.type == 'platform':
    print indent_space + '\
<platform name="' + note.name + '">'
  else:
    print indent_space + '\
<note type="' + note.type + '">'

  items = note.items[:]
  print_textgroup_entry (items, indent, program)

  if note.type == 'platform':
    print indent_space + '\
</platform>'
  else:
    print indent_space + '\
</note>'

# print <item> entry
def print_item_entry (items, indent, program):
  indent_space = ' ' * indent

  sys.stdout.write (indent_space + '<item>')

  while items:
    item = items.pop (0)

    if item.type == 'orderedlist':
      sys.stdout.write ('<orderedlist')
      if item.list_type != 'decimal':
        sys.stdout.write (' type="' + item.list_type + '"')
      if item.start_num != '1':
        sys.stdout.write (' start-num="' + item.start_num + '"')
      sys.stdout.write ('>\n')

      for list_item in item.items:
        if list_item.type == 'item':
          print_item_entry (list_item.items[:], indent + 2, program)

      sys.stdout.write (indent_space + '</orderedlist>')
    elif item.type == 'indent':
      sys.stdout.write ('<indent>\n')
      print_textgroup_entry (item.items[:], indent, program)
      sys.stdout.write (indent_space + '</indent>')
    elif item.type == 'para':
      sys.stdout.write ('<para>' + build_item_text (item, program) + \
                        '</para>')
    elif item.type == 'screen':
      text = cgi.escape (item.text)
      sys.stdout.write ('<screen>\n' + replace_sb_vars (text, program) +
                        '\n' + indent_space + '</screen>')
    elif item.type == 'unorderedlist':
      sys.stdout.write ('<unorderedlist>\n')

      for list_item in item.items:
        if list_item.type == 'item':
          print_item_entry (list_item.items[:], indent + 2, program)

      sys.stdout.write (indent_space + '</unorderedlist>')

    if items:
      sys.stdout.write ('\n' + indent_space)

  print '</item>'

def print_textgroup_entry (items, indent, program):
  indent_space = ' ' * indent

  prev_item_type = None
  while items:
    item = items.pop (0)

    if item.type == 'indent':
      print indent_space + '  <indent>'
      print_textgroup_entry (item.items, indent + 2, program)
      print indent_space + '  </indent>'
    elif item.type == 'orderedlist':
      sys.stdout.write (indent_space + '\
  <orderedlist')
      if item.list_type != 'decimal':
        sys.stdout.write (' type="' + item.list_type + '"')
      if item.start_num != '1':
        sys.stdout.write (' start-num="' + item.start_num + '"')
      sys.stdout.write ('>\n')

      for list_item in item.items:
        if list_item.type == 'item':
          print_item_entry (list_item.items[:], indent + 4, program)

      print indent_space + '\
  </orderedlist>'
    elif item.type == 'para':
      sys.stdout.write (indent_space + '\
  <para')
      if item.align != 'left':
        sys.stdout.write (' align="%s"' % item.align)
      if item.skip != 1:
        sys.stdout.write (' skip="%d"' % item.skip)
      print '>' + build_item_text (item, program) + '</para>'
    elif item.type == 'screen':
      text = cgi.escape (item.text)
      print indent_space + '\
  <screen>\n' + replace_sb_vars (text, program) + '\n' + indent_space + '\
  </screen>'
    elif item.type == 'unorderedlist':
      print indent_space + '\
  <unorderedlist>'

      for list_item in item.items:
        if list_item.type == 'item':
          print_item_entry (list_item.items[:], indent + 4, program)

      print indent_space + '\
  </unorderedlist>'

    # separate some items by newline
    if items:
      if item.type == 'para':
        continue
      if items[0].type not in ['indent', 'orderedlist', 'screen',
                               'unorderedlist']:
        print
